package org.beanutopia.slot;

import org.beanutopia.exception.PropertyDefinitionException;
import org.beanutopia.slot.Slot;
import org.beanutopia.function.Injection;
import static org.beanutopia.function.PropertyFunctions.isInstanceOf;
import com.google.common.base.Function;
import com.google.common.base.Predicate;

import java.util.Map;

/**
 * @author ymeymann
 * @since Dec 17, 2007 2:05:53 PM
 */
public class MapSlot<V> implements Slot<Map,V>, Function<Map,V>, Injection<Map, V> {
  //TODO maybe pool the mappers
  private Object key = null;

  private MapSlot(Object key) {
    this.key = key;
  }

  public static <V> Function<Map,V> reader(String key) {
    return new MapSlot<V>(key);
  }

  public static <V> Injection<Map,V> writer(Object key) {
    return new MapSlot<V>(key);
  }

  public static <V> Slot<Map,V> mapper(Object key) {
    return new MapSlot<V>(key);
  }

  public Function<Map,V> getProjection() {
    return this;
  }

  public Injection<Map,V> getInjection() {
    return this;
  }

  public Slot<Map,V> initialize() throws PropertyDefinitionException {
    return this;
  }

  public Predicate<Object> supported() {
    return isInstanceOf(Map.class);
  }

  @SuppressWarnings({"unchecked"})
  public V apply(Map map) {
    return (V) map.get(key); 
  }

  @SuppressWarnings({"unchecked"})
  public void apply(Map map, V value) {
    map.put(key, value);
  }

}
